#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''事件派发管理器

历史:
    2018-10-24 姚彧 移植
    2018-10-27 ...  多handler支持
'''

__author__ = '姚彧'
__all__ = ['EventContext', 'EventDispatcher']


# ################################ 事件派发管理 ######################################

from tool.Singleton import MetaSingleton


class EventContext(dict):
    @property
    def path(self):
        return self.get('path', None)

    @path.setter
    def path(self, value):
        self['path'] = value


class EventDispatcher(metaclass = MetaSingleton):
    def __init__(self):
        self.__handlers = {}

    @property
    def handler_count(self):
        return len(self.__handlers)

    def __call__(self, path, context, *args, **kwdargs):
        assert (path in self), ('事件未关联处理器', path)
        assert (isinstance(context, EventContext))
        if context.path is None:
            context.path = path
        handlers = self.__handlers.get('*', []) + self.__handlers[path]
        for handler in handlers:
            if handler(context, *args, **kwdargs):
                return True
    emit = __call__

    def register(self, path, handler):
        assert path, path
        assert(callable(handler))
        if path not in self:
            self.__handlers[path] = []
        self.__handlers[path].append(handler)
        return handler

    def unregister_handler(self, path, handler):
        assert(path in self)
        handlers = self.__handlers[path]
        if handler in handlers:
            del handlers[handlers.index(handler)]
        assert(handler not in handlers)

    def unregister(self, path):
        assert(path in self)
        del self.__handlers[path]
        assert (path not in self)

    def clear(self):
        self.__handlers.clear()

    def __contains__(self, path):
        return path in self.__handlers

    def has(self, path, handler = None):
        if path in self.__handlers and handler:
            return handler in self.__handlers[path]
        return False
